package com.supreme.threadserver.service;

import com.supreme.threadserver.config.ThreadPoolTaskConfig;
import com.supreme.threadserver.threadpkg.LoopThread;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.concurrent.ArrayBlockingQueue;

@Service
public class AqsUtilService {

    private static ArrayBlockingQueue<Thread> threadBlockingQueue = new ArrayBlockingQueue<>(4);
    private static ArrayBlockingQueue<LoopThread> loopThreadBlockingQueue = new ArrayBlockingQueue<>(1);

    private static boolean stopConsumer = false;

    public void initLoopThreadBlockQueue(int capacity) {
        threadBlockingQueue = new ArrayBlockingQueue<>(capacity);
    }

    public void stopLoopThreadBlockQueueConsumer() {
        if (!AqsUtilService.stopConsumer) {
            AqsUtilService.stopConsumer = true;
        }
    }

    @Async(value = ThreadPoolTaskConfig.SUPREME_TASK_EXECUTOR)
    public void startLoopThreadBlockQueueConsumer() {
        System.out.println("startLoopThreadBlockQueueConsumer");
        for (;;) {
            try {
                final LoopThread loopThread = loopThreadBlockingQueue.take();
                loopThread.run();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            if (AqsUtilService.stopConsumer) {
                AqsUtilService.stopConsumer = false;
                break;
            }
        }
    }

    public void putThread(int loopCount, long timeout) {
        final LoopThread loopThread = new LoopThread(loopCount, timeout);
        final Thread thread = new Thread(loopThread);
        try {
            threadBlockingQueue.put(thread);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void takeThread() {
        try {
            final Thread takeThread = threadBlockingQueue.take();
            takeThread.start();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public int putLoopThread(int loopCount, long timeout) {
        final LoopThread loopThread = new LoopThread(loopCount, timeout);
        try {
            loopThreadBlockingQueue.put(loopThread);
            return loopThreadBlockingQueue.size();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void takeLoopThread() {
        try {
            final LoopThread loopThread = loopThreadBlockingQueue.take();
            loopThread.run();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
